/* Copyright 2014 Jan Wolter */

#include "stack.h"
#include "tableau.h"
#include "found.h"
#include "bouquet.h"
#include "solve.h"
#include "game.h"

char *gamename= "Trigon";
char *gameopt= "";
Stack *gathered= NULL;
Stack *temp= NULL;

int nplayed= 0;
int nwon= 0;
int cardsleft= 0;
int maxoff;

void setopt(char c) {}

/* This is the main program for setting up the current game */
void exec(int gather, int arif, int over, int cut)
{
    /* Could set things like ndeck, nsuit here */

    /* Build and shuffle the deck */
    Stack *shuf= mixcards(arif, over, cut);

    /* Create the foundations */
    for (int s= 0; s < nsuit; s++)
	makeFound(1, s, +1, 13);

    /* Create the tableau */
    for (int i= 1; i <= 7; i++)
	makeTableau(i, FLIP_ALL, shuf,
	    S_SAMESUIT, -1, S_SAMESUIT, -1, 1, F_KINGLEFT, BREAK_NOWHERE, 0);

    /* Create the waste */
    makeBouquet(shuf,1,0);

    freeStack(shuf);

    if (verbose > 1) printState(stdout, stacks);

    maxoff= 0;
    int win= solve(gather,0);

    if (verbose > 0) printf("maxoff=%d\n",maxoff);
    nplayed++;
    cardsleft+= maxoff;
    if (win) nwon++;

    cleanFound();
    cleanTableau();
    cleanBouquet();
    cleanStacks();
    cleanVisited();
}


void gatherAll()
{
    if (gathered == NULL)
	gathered= allocStack(ncard);
    else
	gathered->n= 0;

    gatherFound(gathered);
    gatherTableau(gathered);
    gatherBouquet(gathered);
    if (gathered->n != ncard)
    {
	printf("Gather Failed - found %d cards\n",gathered->n);
	exit(1);
    }
}

/* How good is a move? Returns 0 if the move is completely safe and should
 * be made immediately without counting this position a a choice point for
 * backtracking. Positive values are lower for better moves. Negative values
 * mean the move should not be done at all.
 */
int rateMove(Stack *src, int index1, int len, Stack *dst)
{
    /* Always safe to move a card to the foundation in Trigon */
    if (dst->type == FOUND) return 0;
    /* Move into non-empty tableau spaces are also safe */
    if (dst->n > 0) return 0;
    /* If the card moving is from the next column, then it is an
     * autofill move and is not only safe but required.
     */
    if (src->type == TABLEAU && src->tid == dst->tid + 1)
	return 0;
    /* Moving a king into an empty tableau space may not be safe, because
     * there might be other kings that we could move. We prefer moving from
     * the tableau over moving from the bouquet.  Among tableau spaces, we
     * prefer moves from taller stacks.
     */
    if (src->type == BOUQUET)
	return ntableau+5; /* Some number bigger than the other case */
    else
	return ntableau - index1;
}

void printState(FILE *f, Stack *stks)
{
    printFound(f, stks);
    printTableau(f, stks);
    printBouquet(f, stks);
}

int victory()
{
    int off= nOff();
    if (off > maxoff) maxoff= off;
    return (off == ncard);
}

/* Return a quality rating for the current solution. Bigger is better. Usually
 * it's just cards off. This is used to decide which solution to report in
 * cases where we never win.
 */
int quality()
{
    return nOff();
}

void summary()
{
    printf("Played:    %d games\n",nplayed);
    printf("Won:       %d games (%.2f%)\n",nwon,(float)nwon*100/nplayed);
    printf("Cards Off: %.2f\n",(float)cardsleft/nplayed);
}

char *currstate() {return NULL;}
